package com.jt.seivice;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatMapper;
import com.jt.pojo.ItemCat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;

@Service
public class ItemCatServiceImpl implements ItemCatService{
    @Autowired
    private ItemCatMapper itemCatMapper;


    /**
     * 弊端: 由于多次循环遍历 查询数据库,导致数据库查询次数太多效率极低.
     * 思路:
     *      1.刚才的业务逻辑梳理
     *      2.如何优化?????   提高效率
     */
//    @Override
//    public List<ItemCat> findItemCatList(Integer level) {
//        //查询一级商品分类信息
//        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("parent_id",0);
//        //100
//        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//        //查询二级商品分类信息
//        for(ItemCat oneItemCat: oneList){
//            //1.为了复用条件构造器 将之前的数据清空
//            queryWrapper.clear();
//            //查询二级数据 parent_id = 一级ID
//            queryWrapper.eq("parent_id",oneItemCat.getId());
//            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
//            //遍历二级列表 查询三级数据,封装数据返回
//            oneItemCat.setChildren(twoList);
//        }
//        return oneList;
//    }

    /**
     * 优化手段:
     *      思路:获取所有的数据库记录,之后按照父子级关系进行封装
     *      数据结构: Map<k,v>
     *               Map<parentId,List当前父级的子级信息(不嵌套)>
     *      例子:     Map<0,List[{id=1,name="xx",children=null}.....]>
     *
     * 封装数据规则:
     *      1.遍历所有的数据.
     *      2.获取parentId
     *      3.判断parentId是否存在,之后实现数据封装
     */

    public Map<Integer,List<ItemCat>> getMap(){
        Map<Integer,List<ItemCat>> map = new HashMap<>();
        //查询所有的数据库记录
        List<ItemCat> list = itemCatMapper.selectList(null);
        //1.遍历数据
        for(ItemCat itemCat:list){
            //获取parentId
            int parentId = itemCat.getParentId();
            if(map.containsKey(parentId)){  //判断集合中是否有key
                //表示数据存在,将自己追加
                map.get(parentId).add(itemCat);
            }else{
                //key不存在, 定义list集合,将自己作为第一个元素追加
                List<ItemCat> childrenList = new ArrayList<>();
                childrenList.add(itemCat);
                //将数据保存到map集合中
                map.put(parentId,childrenList);
            }
        }
        return map;
    }


    //该方法获取1-2级数据信息
    public List<ItemCat>  getTwoList(Map<Integer,List<ItemCat>> map){
        //1.先查询一级菜单数据
        List<ItemCat> oneList = map.get(0);
        //2.遍历每个一级菜单去封装二级数据
        for (ItemCat oneItemCat :oneList){
            int parentId = oneItemCat.getId();
            //查询二级数据
            List<ItemCat> twoList = map.get(parentId);
            oneItemCat.setChildren(twoList);
        }
        return oneList;
    }


    /**
     *      实现思路:
     *              1.  获取二级分类列表数据
     *              2.  遍历一级菜单,获取二级数据
     *              3.  根据二级菜单查询三级数据        防止二级数据为空的现象
     *              4.  将三级数据封装到二级中
     */
    public List<ItemCat> getThreeList(Map<Integer,List<ItemCat>> map){
        //1.获取1-2级数据信息      包含了2级的children
        List<ItemCat> oneList = getTwoList(map);
        //2.遍历一级的数据,获取二级数据
        for (ItemCat oneItemCat : oneList){
            List<ItemCat> twoList = oneItemCat.getChildren();
            if (twoList ==null || twoList.size()==0){
                continue;//跳过本次循环,进入下一次循环
            }
        //3.遍历二级数据,查询三级数据
        for (ItemCat twoItemList:twoList){
            //查询三级      parentId = 二级Id
                    int parentId = twoItemList.getId();
            List<ItemCat> threeList = map.get(parentId);
       //4.将三级封装到二级中
            twoItemList.setChildren(threeList);
            }
        }
        return oneList;
    }

    /**
     * 如果使用常规的写法     耗时:900毫秒
     *                                      经过优化:20毫秒
     * @param level
     * @return
     */

    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        //获取所有集合数据
        Map<Integer, List<ItemCat>> map = getMap();

        if (level == 1) {
            //一级商品分类信息
            return map.get(0);
        }
        if (level == 2) {//获取一级和二级菜单
            return getTwoList(map);
        }
        //获取三级惨淡数据
        return getThreeList(map);
    }




    /**
     *  业务:如果是父级  则应该删除子级和子级
     *  思路:
     *          1.  判断是否为3级标签       直接删除
     *          2.  判断是否为2级标签       先删除三级再删除二级
     *          3.  判断是否为1级标签       先查询二级,再删除三级和二级再删除一级
     */
    @Override
    @Transactional
    public void deleteItemCat(ItemCat itemCat) {
        if (itemCat.getLevel()==3){
            int id = itemCat.getId();
            itemCatMapper.deleteById(id);
            return;
        }
        if (itemCat.getLevel()==2){
            //sql:    xxx  where parent_id = 二级id
            int id = itemCat.getId();
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("parent_id", id);
            itemCatMapper.delete(queryWrapper);
            itemCatMapper.deleteById(id);
            return;
        }

        /**
         * 删除一级菜单
         */
        //1.查询二级数据  sql:  where parent_id = id
        QueryWrapper queryWrapper = new QueryWrapper();
        int id = itemCat.getId();
        queryWrapper.eq("parent_id", id);
        //由于是删除的业务,只需要获取id即可  所以使用Objs  二级id
        List idList = itemCatMapper.selectObjs(queryWrapper);
        if (idList.size()>0) {
            //根据二级id删除三级数据?  sql: where parent_id in (1,2,3)
            queryWrapper.clear();
            queryWrapper.in("parent_id", idList);
            itemCatMapper.delete(queryWrapper);
            //删除二级和一级
            idList.add(id);//将所有一二级的id,封装到一个集合中
            itemCatMapper.deleteBatchIds(idList);
        }else {
            itemCatMapper.deleteById(id);
        }
    }




    //优化:自动生成时间--自动填充功能
    @Override
    @Transactional      //事务管理
    public void saveItemCat(ItemCat itemCat) {
        Date date = new Date();
        //itemCat.setStatus(true).setCreated(date).setUpdated(date);
        itemCat.setStatus(true);
        itemCatMapper.insert(itemCat);
    }

    @Override
    @Transactional
    public void updatestatus(ItemCat itemCat) {
        //itemCat.setUpdated(new Date());  不用写 应为有自动填充
       itemCatMapper.updateById(itemCat);
    }

    @Override
    @Transactional
    public void updateItemCat(ItemCat itemCat) {
        //itemCat.setUpdated(new Date());   不用写 应为有自动填充
        ItemCat temp = new ItemCat();
        temp.setId(itemCat.getId()).setName(itemCat.getName());
        itemCatMapper.updateById(temp);
    }
}
